package start.from.scratch.love.common.util;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class AESUtil {
    private static final String CIPHER_TYPE = "AES";
    private static final byte[] key = "love@*2%0.~$!#^&".getBytes();
    private static final SecretKey secretKey = new SecretKeySpec(key, CIPHER_TYPE);
    /**
     * 对给定字段进行加密, 使用默认 secretKey
     * @param raw
     * @return
     * @throws Exception
     */
    public static String encode (String raw) throws Exception {
        return encode(raw, secretKey);
    }

    public static String encode (String raw, String key) throws Exception {
        return encode(raw, new SecretKeySpec(key.getBytes(), CIPHER_TYPE));
    }

    public static String encode (String raw, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_TYPE);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherByte = cipher.doFinal(raw.getBytes());
        cipherByte = Base64.getEncoder().encode(cipherByte);
        return new String(cipherByte);
    }

    /**
     * 对给定字段进行解密, 使用默认 secretKey
     * @param raw
     * @return
     * @throws Exception
     */
    public static String decode (String raw) throws Exception {
        return decode(raw, secretKey);
    }

    public static String decode (String raw, String key) throws Exception {
        return decode(raw, new SecretKeySpec(key.getBytes(), CIPHER_TYPE));
    }

    public static String decode (String raw, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_TYPE);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] cipherByte = Base64.getDecoder().decode(raw.getBytes());
        cipherByte = cipher.doFinal(cipherByte);
        return new String(cipherByte);
    }

    public static byte[] getKey(KeyLen len){
        try {
            KeyGenerator generator = KeyGenerator.getInstance(CIPHER_TYPE);
            generator.init(len.getLen());
            return generator.generateKey().getEncoded();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("generate key exception", e);
        }
    }

    public static String getKeyStr32(){
        return bytesToHex(getKey(KeyLen.LEN_128));
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    public enum KeyLen {
        LEN_128(128),
        LEN_192(192),
        LEN_256(256)
        ;

        private int len;

        KeyLen(int len) {
            this.len = len;
        }

        public int getLen() {
            return len;
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println(encode("xfy@930112"));
        System.out.println(AESUtil.decode("hSkk2nfJy/zEsbuyfI3dpQ=="));
    }
}
